/**
 * 
 */
package uk.ac.ebi.velvet.model.impl;

import org.apache.commons.lang.NotImplementedException;

import uk.ac.ebi.velvet.model.MapLocation;
import uk.ac.ebi.velvet.model.ReadData;
import uk.ac.ebi.velvet.model.Strand;

/**
 * @author mhaimel
 *
 */
public class ReadDataImpl implements ReadData {

	private volatile MapLocation fwdRead = null;
	private volatile MapLocation rvsRead = null;
	private volatile int length = -1;
	private volatile int identifier = -1;
	private volatile long fwdPos = -1;
	private volatile long revPos = -1;
	private volatile boolean paired = false;

	public ReadDataImpl() {
		// do nothing
	}
	
	public ReadDataImpl(int identifier) {
		this.identifier = identifier;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb	.append("Identifier: ")
			.append(identifier)
			.append("; Global file position: ")
			.append(fwdPos)
			.append(":")
			.append(revPos)
			.append("; Length: ")
			.append(length)
			.append("; Has Fwd:Rev:unpaired: ")
			.append(hasForwardRead())
			.append(":")
			.append(hasReverseRead())
			.append(":")
			.append(hasUnpairedRead())
			.append(";");
		return sb.toString();
	}
	
	public void setLength(int length) {
		this.length = length;
	}

	@Override
	public int getIdentifier() {
		return this.identifier;
	}
	
	public boolean isPaired() {
		return paired;
	}

	public void setPaired(boolean paired) {
		this.paired = paired;
	}

	@Override
	public int getLenth() {
		return length;
	}

	@Override
	public MapLocation getPairedRead(Strand str) {
		if(Strand.FWD.equals(str)){
			return getForwardRead();
		} else if (Strand.REV.equals(str)){
			return getReverseRead();
		} else {
			throw new NotImplementedException("Not yet implemented for :" + str);
		}
	}

	@Override
	public MapLocation getUnpairedRead() {
		return fwdRead;
	}

	@Override
	public boolean hasPairedRead(Strand str) {
		if(Strand.FWD.equals(str)){
			return hasForwardRead();
		} else if (Strand.REV.equals(str)){
			return hasReverseRead();
		} else {
			throw new NotImplementedException("Not yet implemented for :" + str);
		}
	}

	@Override
	public boolean hasUnpairedRead() {
		return isPaired()?false:null != fwdRead;
	}

	private void setUnpairedRead(MapLocation unpaired) {
		setPaired(false);
		this.fwdRead = unpaired;
	}
	
	private MapLocation getReverseRead() {
		return rvsRead;
	}
	private boolean hasReverseRead() {
		return rvsRead != null;
	}
	private void setReverseRead(MapLocation loc) {
		setPaired(true);
		this.rvsRead = loc;
	}
	private MapLocation getForwardRead() {
		return isPaired()?fwdRead:null;
	}
	private boolean hasForwardRead() {
		return isPaired()?
				fwdRead != null
				:false;
	}
	
	private void setForwardRead(MapLocation loc) {
		setPaired(true);
		this.fwdRead = loc;
	}

	@Override
	public void setRead(MapLocation loc) {
		Strand str = loc.getReadOrientation();
		if(null == str || Strand.UNKOWN.equals(str)){
			setUnpairedRead(loc);
		} else if(Strand.FWD.equals(str)){
			setForwardRead(loc);
		} else if (Strand.REV.equals(str)){
			setReverseRead(loc);
		} else {
			throw new NotImplementedException("Not yet implemented for :" + str);
		}	
	}

	@Override
	public long getFilePosition() {
		return isPaired()?-1:fwdPos;
	}
	
	public void setFilePosition(long filePosition) {
		setPaired(false);
		this.fwdPos = filePosition;
	}

	@Override
	public Long getFilePosition(Strand str) {
		if(null == str || Strand.UNKOWN.equals(str)){
			return getFilePosition();
		} else if(Strand.FWD.equals(str)){
			return fwdPos;
		} else if (Strand.REV.equals(str)){
			return revPos;
		} else {
			throw new NotImplementedException("Not yet implemented for :" + str);
		}	
	}

	@Override
	public void setFilePosition(Strand str, Long pos) {
		if(null == str || Strand.UNKOWN.equals(str)){
			setFilePosition(pos);
		} else if(Strand.FWD.equals(str)){
			setPaired(true);
			fwdPos = pos;
		} else if (Strand.REV.equals(str)){
			setPaired(true);
			revPos = pos;
		} else {
			throw new NotImplementedException("Not yet implemented for :" + str);
		}			
	}
}
